package com.suny.dingd_demo.client.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.availability.ApplicationAvailability;
import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.availability.LivenessState;
import org.springframework.boot.availability.ReadinessState;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/test")
public class TestController {

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private ApplicationAvailability applicationAvailability;

    @GetMapping("/health")
    public Map<String, Object> healthCheck() {
        Map<String, Object> result = new HashMap<>();
        result.put("status", "UP");
        result.put("message", "Service is running");
        result.put("timestamp", System.currentTimeMillis());
        return result;
    }

    @GetMapping("/error")
    public Map<String, Object> triggerError() {
        Map<String, Object> result = new HashMap<>();
        result.put("status", "ERROR");
        result.put("message", "Service state changed to BROKEN");
        result.put("timestamp", System.currentTimeMillis());
        
        // 发布状态变更事件
        AvailabilityChangeEvent.publish(applicationContext, this, LivenessState.BROKEN);
        
        return result;
    }

    @GetMapping("/memory")
    public Map<String, Object> memoryStatus() {
        Map<String, Object> result = new HashMap<>();
        Runtime runtime = Runtime.getRuntime();
        
        long totalMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        long maxMemory = runtime.maxMemory();
        long usedMemory = totalMemory - freeMemory;
        
        result.put("total", formatSize(totalMemory));
        result.put("free", formatSize(freeMemory));
        result.put("used", formatSize(usedMemory));
        result.put("max", formatSize(maxMemory));
        
        return result;
    }

    private String formatSize(long size) {
        String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
        int unitIndex = 0;
        double sizeInUnit = size;
        
        while (sizeInUnit >= 1024 && unitIndex < units.length - 1) {
            sizeInUnit /= 1024;
            unitIndex++;
        }
        
        return String.format("%.2f %s", sizeInUnit, units[unitIndex]);
    }

    @GetMapping("/down")
    public Map<String, Object> down() {
        Map<String, Object> result = new HashMap<>();
        result.put("status", "DOWN");
        result.put("message", "Service is refusing traffic");
        result.put("timestamp", System.currentTimeMillis());
        
        // 发布服务下线事件
        AvailabilityChangeEvent.publish(applicationContext, this, ReadinessState.REFUSING_TRAFFIC);
        
        return result;
    }

    @GetMapping("/up")
    public Map<String, Object> up() {
        Map<String, Object> result = new HashMap<>();
        result.put("status", "UP");
        result.put("message", "Service is accepting traffic");
        result.put("timestamp", System.currentTimeMillis());
        
        // 发布服务上线事件
        AvailabilityChangeEvent.publish(applicationContext, this, ReadinessState.ACCEPTING_TRAFFIC);
        
        return result;
    }

    @GetMapping("/status")
    public Map<String, Object> getStatus() {
        Map<String, Object> result = new HashMap<>();
        result.put("liveness", applicationAvailability.getLivenessState());
        result.put("readiness", applicationAvailability.getReadinessState());
        result.put("timestamp", System.currentTimeMillis());
        return result;
    }

    @GetMapping("/broken")
    public String broken() {
        // 模拟服务故障
        AvailabilityChangeEvent.publish(eventPublisher, this, LivenessState.BROKEN);
        return "Service is now BROKEN";
    }

    @GetMapping("/correct")
    public String correct() {
        // 模拟服务恢复
        AvailabilityChangeEvent.publish(eventPublisher, this, LivenessState.CORRECT);
        return "Service is now CORRECT";
    }

    @GetMapping("/recover")
    public Map<String, Object> recover() {
        Map<String, Object> result = new HashMap<>();
        result.put("status", "RECOVERED");
        result.put("message", "Service state restored to CORRECT");
        result.put("timestamp", System.currentTimeMillis());
        
        // 发布状态恢复事件
        AvailabilityChangeEvent.publish(applicationContext, this, LivenessState.CORRECT);
        
        return result;
    }
} 